package com.ctshk.rpc.order.bus.service.impl;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.OrderPaymentStatus;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.service.support.BaseService;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.bus.dto.BusLineDTO;
import com.ctshk.rpc.bus.service.IBusLineService;
import com.ctshk.rpc.order.bus.dto.BusOrderPayDTO;
import com.ctshk.rpc.order.bus.dto.MyBusOrderDTO;
import com.ctshk.rpc.order.bus.entity.BusOrder;
import com.ctshk.rpc.order.bus.mapper.BusOrderMapper;
import com.ctshk.rpc.order.bus.req.BusCancelOrderReq;
import com.ctshk.rpc.order.bus.req.BusOrderCreateB2CReq;
import com.ctshk.rpc.order.bus.req.BusOrderPayReq;
import com.ctshk.rpc.order.bus.service.IBusOrderAppService;
import com.ctshk.rpc.order.bus.service.IBusOrderService;
import com.ctshk.rpc.user.service.IOrderEsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * <p>
 * 巴士订单表 服务实现类
 * </p>
 *
 * @author 彭柳霖
 * @since 2021-02-24
 */
@Slf4j
@DubboService
public class BusOrderAppServiceImpl extends ServiceImpl<BusOrderMapper, BusOrder> implements IBusOrderAppService, BaseService {

    @DubboReference
    IBusOrderService busOrderService;

    @DubboReference
    private IBusLineService busLineService;

    @DubboReference
    private IOrderEsService orderEsService;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    /**
     * 填写订单信息下单
     *
     * @param busOrderWriteReq
     * @param user
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Long> writeBusOrder(BusOrderCreateB2CReq busOrderWriteReq, TokenUser user) {
        Long userId = null;
        if (ObjectUtils.isNotEmpty(userId)) {
            userId = user.getId();
        }
        Result<Long> result = busOrderService.addBusOrderB2C(busOrderWriteReq, userId);
        if(result.isSuccess()) {
            sendOrderToAppUser(result.getData());
        }
        return result;
    }

    /**
     * 巴士订单支付结果
     *
     * @param busOrderPayReq
     * @return
     */
    @Override
    public Result busOrderPay(BusOrderPayReq busOrderPayReq) {
        BusOrder busOrder = baseMapper.selectById(busOrderPayReq.getId());
        // 订单是否存在
        if (null == busOrder) {
            return Result.failed(SystemError.BUS_ORDER_9005);
        }
        // 查看订单支付状态
        if (busOrder.getPaymentStatus().equals(OrderPaymentStatus.ALREADY_PAYMENT.getCode())) {
            return Result.failed(SystemError.BUS_ORDER_9012);
        }
        // 查看订单支付金额与前端传递金额是否一致
        if (!busOrderPayReq.getPayAmount().equals(busOrder.getOrderAmount())) {
            return Result.failed(SystemError.BUS_ORDER_9004);
        }

        BusOrderPayDTO busOrderPayDTO = new BusOrderPayDTO();
        busOrderPayDTO.setPayType(busOrderPayReq.getPayType());
        busOrderPayDTO.setPayTime(LocalDateTime.now());
        busOrderPayDTO.setInquiryNumber(busOrder.getInquiryNumber());
        busOrderPayDTO.setOrderNumber(busOrder.getOrderNumber());
        busOrderPayDTO.setId(busOrder.getId());
        return Result.success(busOrderPayDTO);
    }

    /**
     * 取消订单
     *
     * @param id
     * @return
     */
    @Override
    public Result busOrderCancel(Long id, TokenUser user) {
        BusCancelOrderReq busCancelOrderReq = new BusCancelOrderReq();
        busCancelOrderReq.setOrderId(id);
        busCancelOrderReq.setRefundReason(OrderPaymentStatus.UN_PAYMENT.getName());
        Result result = busOrderService.cancelOrder(busCancelOrderReq, user);
        if(result.isSuccess()) {
            updateStatusToAppUser(id);
        }
        return result;
    }

    /**
     * 执行 K:V 缓存删除
     *
     * @param keys 需要删除的keys
     * @return
     */
    private Map<String, Boolean> deletString(List<String> keys) {
        Map<String, Boolean> map = new HashMap<>();
        keys.forEach(key -> {
            Boolean delete = redisTemplate.delete(key);
            map.put(key, delete);
        });
        return map;
    }

    /**
     * 构建订单ESDTO
     * @param orderId
     * @return
     */
    public MyBusOrderDTO buildEsOrderDTO(Long orderId) {
        MyBusOrderDTO orderDTO = baseMapper.selectById(MyBusOrderDTO.class, orderId);
        BusLineDTO busLineDTO = busLineService.queryByLineId(orderDTO.getLineId());
        if(busLineDTO != null) {
            busLineDTO.setEstimatedTime(busLineDTO.getEstimatedTime());
        }

        return orderDTO;
    }

    /**
     * 异步发送订单数据到个人中心
     * @param orderId 订单Id
     */
    public void sendOrderToAppUser(Long orderId) {
        CompletableFuture.runAsync(() -> {
            try {
                MyBusOrderDTO orderDTO = buildEsOrderDTO(orderId);
                orderEsService.saveOrderToEs(orderDTO, SystemBusinessType.BUS_TICKET);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 异步更新订单状态到个人中心
     */
    public void updateStatusToAppUser(Long orderId) {
        CompletableFuture.runAsync(() -> {
            try {
                BusOrder order = baseMapper.selectById(orderId);
                orderEsService.updateStatusToEs(order.getId(),SystemBusinessType.BUS_TICKET.getCode(),
                        null, order.getPaymentStatus(), order.getScheduledStatus(),
                        order.getCancelStatus());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

}
